package com.fanketly.funacg2.utils

import android.app.Activity
import android.util.Log
import java.util.*

object ActivityUtils {
    private val mActivityList = LinkedList<Activity>()

    fun getTopActivity(): Activity? {
        val activityList = getActivityList()
        for (activity in activityList) {
            if (!isActivityAlive(activity)) {
                continue
            }
            return activity
        }
        return null
    }


    fun getActivityList(): LinkedList<Activity?> {
        if (!mActivityList.isEmpty()) {
            return LinkedList(mActivityList)
        }
        val reflectActivities = getActivitiesByReflect()
        mActivityList.addAll(reflectActivities)
        return LinkedList(mActivityList)
    }

    private fun isActivityAlive(activity: Activity?): Boolean {
        return (activity != null && !activity.isFinishing && !activity.isDestroyed)
    }

    private fun getActivitiesByReflect(): List<Activity> {
        val list = LinkedList<Activity>()
        var topActivity: Activity? = null
        try {
            val activityThread: Any = getActivityThread() ?: return list
            val mActivitiesField = activityThread.javaClass.getDeclaredField("mActivities")
            mActivitiesField.isAccessible = true
            val mActivities = mActivitiesField[activityThread] as? Map<*, *> ?: return list
            for (activityRecord in mActivities.values) {
                val activityClientRecordClass: Class<*> = activityRecord!!.javaClass
                val activityField = activityClientRecordClass.getDeclaredField("activity")
                activityField.isAccessible = true
                val activity = activityField[activityRecord] as Activity
                if (topActivity == null) {
                    val pausedField = activityClientRecordClass.getDeclaredField("paused")
                    pausedField.isAccessible = true
                    if (!pausedField.getBoolean(activityRecord)) {
                        topActivity = activity
                    } else {
                        list.addFirst(activity)
                    }
                } else {
                    list.addFirst(activity)
                }
            }
        } catch (e: Exception) {
            Log.e("UtilsActivityLifecycle", "getActivitiesByReflect: " + e.message)
        }
        if (topActivity != null) {
            list.addFirst(topActivity)
        }
        return list
    }

    private fun getActivityThread(): Any? {
        val activityThread: Any? = getActivityThreadInActivityThreadStaticField()
        return activityThread ?: getActivityThreadInActivityThreadStaticMethod()
    }

    private fun getActivityThreadInActivityThreadStaticField(): Any? {
        return try {
            val activityThreadClass = Class.forName("android.app.ActivityThread")
            val sCurrentActivityThreadField =
                activityThreadClass.getDeclaredField("sCurrentActivityThread")
            sCurrentActivityThreadField.isAccessible = true
            sCurrentActivityThreadField[null]
        } catch (e: java.lang.Exception) {
            Log.e(
                "UtilsActivityLifecycle",
                "getActivityThreadInActivityThreadStaticField: " + e.message
            )
            null
        }
    }

    private fun getActivityThreadInActivityThreadStaticMethod(): Any? {
        return try {
            val activityThreadClass = Class.forName("android.app.ActivityThread")
            activityThreadClass.getMethod("currentActivityThread").invoke(null)
        } catch (e: java.lang.Exception) {
            Log.e(
                "UtilsActivityLifecycle",
                "getActivityThreadInActivityThreadStaticMethod: " + e.message
            )
            null
        }
    }
}